<?php

namespace App\Http\Controllers\Web;

use Illuminate\Http\Request;
use DB;

class TestController extends BaseController
{
    public function weixinlogin()
    {
        // 第一步：请求CODE
        $config = Config('common.wxmp');
        $previous = url()->full(); // 获取当前页面URL
        $callbackUrl = Config('app.url') . '/test/weixinlogin_callback?previous=' . urlencode($previous); //请求成功返回URL
        $scope = 'snsapi_base'; //静默登录 是用来获取进入页面的用户的openid的，并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页
        $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $config['AppID'] . '&redirect_uri=' . $callbackUrl . '&response_type=code&scope=' . $scope . '&state=STATE#wechat_redirect';
        header("location: $url");
    }

    public function weixinlogin_callback(Request $request)
    {
        // 第二步：通过code换取网页授权access_token
        $code = $request->code;
        $config = Config('common.wxmp');
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' .  $config['AppID'] . '&secret=' . $config['AppSecret'] . '&code=' . $code . '&grant_type=authorization_code';
        $res = curl_get($url);
        $res = json_decode($res, 1);
        dd($res);

        // 用户登录注册逻辑
        // ......
    }

    public function weixinpay_notify(Request $request)
    {
        $config_mp = Config('common.wxmp');
        $config_mc = Config('common.wxmc');

        $postStr = file_get_contents('php://input');
        // 禁止引用外部xml实体
		libxml_disable_entity_loader(true);
        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);

        // 验证
        if ($postObj === false) {
            die('parse xml error');
        }
        if ($postObj->return_code != 'SUCCESS') {
            die($postObj->return_msg);
        }
        if ($postObj->result_code != 'SUCCESS') {
            die($postObj->err_code);
        }

        $array = (array)$postObj;
        unset($array['sign']);
        if ($this->getSign($array, $config_mc['apiKey']) == $postObj->sign) {
            echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';

            // 处理支付成功后的逻辑
            // out_trade_no订单编号
            // ......
        }

        logWrite(json_encode($postObj), 'weixinpay');
    }

    public function weixinpay_jsapi()
    {
        $config_mp = Config('common.wxmp');
        $config_mc = Config('common.wxmc');

        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $params = [
            'appid' => $config_mp['AppID'],
            'mch_id' => $config_mc['mchid'],
            'nonce_str' => $this->createNonceStr(),
            'body' => '金币充值',
            'out_trade_no' => 'i' . time(),
            'total_fee' => 1,
            'spbill_create_ip' => '127.0.0.1',
            'notify_url' => Config('app.url') . '/test/weixinpay_notify',
            'trade_type' => 'JSAPI',
            'openid' => 'oWAsD59090vREg3XLq5VJVqlVcZQ',
        ];

        $sign = $this->getSign($params, $config_mc['apiKey']);
        $params['sign'] = $sign;
        $xml = $this->arrayToXml($params);
        $responseXml = curl_post($url, $xml);

        //禁止引用外部xml实体
		libxml_disable_entity_loader(true);
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($unifiedOrder === false) {
            die('parse xml error');
        }
        if ($unifiedOrder->return_code != 'SUCCESS') {
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
            die($unifiedOrder->err_code);
        }

        $array = array(
            "appId" => $config_mp['AppID'],
            "timeStamp" => (string)time(),
            "nonceStr" => self::createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => 'MD5',
        );
        $array['paySign'] = self::getSign($array, $config_mc['apiKey']);
        return jsonSuccess($array);
        dd($unifiedOrder);

    }

    private function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    private function getSign($params, $key)
    {
        ksort($params, SORT_STRING); // 根据首字母正序排序
        $unSignParaString = $this->formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); //把所有字符转换为大写
        return $signStr;
    }

    private static function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v); //urlencode转码 不能出现特殊字符或空格
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1); //去除字符串中的最后一个字符
        }

        return $reqPar;
    }

    private function createNonceStr($length = 16)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
}
